package org.wtframework.platform.server.log;  
  
import java.lang.reflect.Method;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.openredhead.springx.core.server.service.Securitys;
import org.openredhead.springx.core.server.util.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.wtframework.platform.server.manager.impl.LogRecordManager;
import org.wtframework.platform.server.model.impl.LogRecord;
import org.wtframework.platform.server.model.impl.User;
  
/** 
 */  
@Aspect  
@Component  
public  class SystemLogAspect {

	
    //注入Service用于把日志保存数据库  
    @Resource  
    private LogRecordManager logService;
    //本地异常日志记录对象  
     private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);  
  
    //Service层切点  
    @Pointcut("@annotation(org.wtframework.platform.server.log.SystemServiceLog)")  
     public  void serviceAspect() {  
    }  
  
    //Controller层切点  
    @Pointcut("@annotation(org.wtframework.platform.server.log.SystemControllerLog)")  
     public  void controllerAspect() {  
    }  
  
    /** 
     * 前置通知 用于拦截Controller层记录用户的操作 
     * 
     * @param joinPoint 切点 
     */  
//     @Before("controllerAspect()")  
     public  void doBefore(JoinPoint joinPoint) {  
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
        //读取的用户  
        User user = Securitys.getAuthenticationUser().getUser();
        //请求的IP  
        String ip = request.getRemoteAddr();  
         try {  
            //*========控制台输出=========*//  
           /* System.out.println("=====前置通知开始=====");  
            System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
            System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));  
            System.out.println("请求人:" + user.getNickname());  
            System.out.println("请求IP:" + ip);  */
        	System.out.println("行为记录:" + getControllerMethodDescription(joinPoint));
            //*========数据库日志=========*//  
            LogRecord log = new LogRecord();  
            log.setDescription(getControllerMethodDescription(joinPoint));  
            log.setMethods((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
            log.setType("0");  
            log.setReqIp(ip);  
            log.setExceptionCode( null);  
            log.setExceptionDetail( null);  
            log.setParams( null);  
            log.setUser(user.getNickname());
            log.setUserid(user.getId());
            log.setResult(1);
            //保存数据库  
            logService.save(log);  
            
//            System.out.println("=====前置通知结束=====");  
        }  catch (Exception e) {  
            //记录本地异常日志  
            logger.error("==前置通知异常==");  
            logger.error("异常信息:{}", e.getMessage());  
        }  
    }  
     
    
     
     public void saveLog(String contents,String methods){

         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
         //读取的用户  
         User user = Securitys.getAuthenticationUser().getUser();  
         //请求的IP  
         String ip = request.getRemoteAddr();  
          try {  
             //*========控制台输出=========*//  
            /* System.out.println("=====前置通知开始=====");  
             System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
             System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));  
             System.out.println("请求人:" + user.getNickname());  
             System.out.println("请求IP:" + ip);  */
         	System.out.println("行为记录:" + contents);
             //*========数据库日志=========*//  
             LogRecord log = new LogRecord();  
             log.setDescription(contents);  
             log.setMethods(methods);  
             log.setType("0");  
             log.setReqIp(ip);  
             log.setExceptionCode( null);  
             log.setExceptionDetail( null);  
             log.setParams( null);
             if(user == null){
            	 log.setUser(null);
            	 log.setUserid(null);
             }else{
            	 log.setUser(user.getNickname());
            	 log.setUserid(user.getId());
             }
             log.setResult(1);
             //保存数据库  
             logService.save(log);  
             
//             System.out.println("=====前置通知结束=====");  
         }  catch (Exception e) {  
             //记录本地异常日志  
             logger.error("==前置通知异常==");  
             logger.error("异常信息:{}", e.getMessage());  
         }
     }
     
     
     @Before("controllerAspect()")  
     public  void doAfter(JoinPoint joinPoint) {  
            try {
				saveLog(getControllerMethodDescription(joinPoint),(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    }
    
     
     @After("serviceAspect()")  
     public  void doServiceAspect(JoinPoint joinPoint) {  
            try {
				saveLog(getServiceMthodDescription(joinPoint),(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    }
     
     /** 
     * 异常通知 用于拦截service层记录异常日志 
     * 
     * @param joinPoint 
     * @param e 
     */  
//     @AfterThrowing(pointcut = "serviceAspect()", throwing = "e") 
     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 
        //读取session中的用户  
        User user = Securitys.getAuthenticationUser().getUser();  
        //获取请求ip  
        String ip = request.getRemoteAddr();  
        //获取用户请求方法的参数并序列化为JSON格式字符串  
        String params = "";  
         if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {  
             for ( int i = 0; i < joinPoint.getArgs().length; i++) {  
                params += JsonUtils.encode(joinPoint.getArgs()[i]) + ";";  
            }  
        }  
         try {  
              /*========控制台输出=========*/  
            /*System.out.println("=====异常通知开始=====");  
            System.out.println("异常代码:" + e.getClass().getName());  
            System.out.println("异常信息:" + e.getMessage());  
            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
            System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));  
            System.out.println("请求人:" + user.getNickname());  
            System.out.println("请求IP:" + ip);  
            System.out.println("请求参数:" + params);*/  
               /*==========数据库日志=========*/  
            LogRecord log = new LogRecord();  
            log.setDescription(getServiceMthodDescription(joinPoint));  
            log.setExceptionCode(e.getClass().getName());  
            log.setType("1");  
            log.setExceptionDetail(e.getMessage());  
            log.setMethods((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
            log.setParams(params);  
            log.setUser(user.getNickname());
            log.setUserid(user.getId()); 
            log.setReqIp(ip);
            log.setResult(0);
            //保存数据库  
            logService.save(log);  
//            System.out.println("=====异常通知结束=====");  
        }  catch (Exception ex) {  
            //记录本地异常日志  
            logger.error("==异常通知异常==");  
            logger.error("异常信息:{}", ex.getMessage());  
        }  
         /*==========记录本地异常日志==========*/  
        logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);  
  
    }  
  
  
    /** 
     * 获取注解中对方法的描述信息 用于service层注解 
     * 
     * @param joinPoint 切点 
     * @return 方法描述 
     * @throws Exception 
     */  
     public  static String getServiceMthodDescription(JoinPoint joinPoint)  
             throws Exception {  
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class targetClass = Class.forName(targetName);  
        Method[] methods = targetClass.getMethods();  
        String description = "";  
         for (Method method : methods) {  
             if (method.getName().equals(methodName)) {  
                Class[] clazzs = method.getParameterTypes();  
                 if (clazzs.length == arguments.length) {  
                    description = method.getAnnotation(SystemServiceLog. class).description();  
                     break;  
                }  
            }  
        }  
         return description;  
    }  
  
    /** 
     * 获取注解中对方法的描述信息 用于Controller层注解 
     * 
     * @param joinPoint 切点 
     * @return 方法描述 
     * @throws Exception 
     */  
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {  
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class targetClass = Class.forName(targetName);  
        Method[] methods = targetClass.getMethods();  
        String description = "";  
         for (Method method : methods) {  
             if (method.getName().equals(methodName)) {  
                Class[] clazzs = method.getParameterTypes();  
                 if (clazzs.length == arguments.length) {  
                    description = method.getAnnotation(SystemControllerLog. class).description();  
                     break;  
                }  
            }  
        }  
         return description;  
    }  
}  